package com.gym.code.generator.impl.dao;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import com.gym.code.config.admin.bean.method.MethodBaseMappingBean.MethodParameterCombineType;
import com.gym.code.config.admin.bean.method.MethodBaseMappingBean.MethodResultType;
import com.gym.code.generator.Contants;
import com.gym.code.generator.EnumContants.FieldClassType;
import com.gym.code.generator.fmt.FreemarkerUtil;
import com.gym.code.generator.fmt.model.FmtFieldModel;
import com.gym.code.generator.impl.dao.sql.impl.DeleteSqlGenerator;
import com.gym.code.generator.impl.dao.sql.impl.InsertSqlGenerator;
import com.gym.code.generator.impl.dao.sql.impl.QuerySqlGenerator;
import com.gym.code.generator.impl.dao.sql.impl.UpdateSqlGenerator;
import com.gym.code.generator.model.mapping.field.EnumFieldGenerateModel;
import com.gym.code.generator.model.mapping.field.FieldGenerateModel;
import com.gym.code.generator.model.mapping.field.ParameterFieldGenerateModel;
import com.gym.code.generator.model.mapping.field.ParameterListValueFieldGenerateModel;
import com.gym.code.generator.model.mapping.field.ParameterRangeFieldGenerateModel;
import com.gym.code.generator.model.mapping.layer.LayerGenerateModel;
import com.gym.code.generator.model.mapping.layer.dao.DaoLayerGenerateModel;
import com.gym.code.generator.model.mapping.method.AbstractMethodGenerateModel;
import com.gym.code.generator.model.mapping.method.MethodDeleteModel;
import com.gym.code.generator.model.mapping.method.MethodInsertModel;
import com.gym.code.generator.model.mapping.method.MethodSelectModel;
import com.gym.code.generator.model.mapping.method.MethodUpdateModel;
import com.gym.code.generator.utils.LocalStringUtils;

/**
 * 
 * @author xinchun.wang 
   @email: 532002108@qq.com
 * @createTime 2015-4-12 上午11:30:46
 */
public class DaoImplGenerator extends AbstractDaoGenerator<DaoLayerGenerateModel> {
	
	private DaoImplGenerator(){}
	
    private static DaoImplGenerator instance = new DaoImplGenerator();
	
	public static DaoImplGenerator getInstance(){
		return instance;
	}
	
	private static QuerySqlGenerator querySqlGenerator = QuerySqlGenerator.getInstance();
	private static DeleteSqlGenerator deleteSqlGenerator = DeleteSqlGenerator.getInstance();
	private static UpdateSqlGenerator updateSqlGenerator = UpdateSqlGenerator.getInstance();
	private static InsertSqlGenerator insertSqlGenerator = InsertSqlGenerator.getInstance();
	
	@Override
	protected List<String> generateClassBegin(DaoLayerGenerateModel bean) {
		List<String> result = new ArrayList<String>();
		result.add("@Repository");
		result.add("public class " + getDaoName(bean) + " implements " + bean.getDaoFaceName() + " {");
		return result;
	}
	
	
	protected String getDaoName(DaoLayerGenerateModel bean){
		if(StringUtils.isNotEmpty(bean.getDaoName())){
			return bean.getDaoName();
		}else {
			return bean.getBeanGenerateModel().getBeanName()+"Dao";
		}
	}
	
	protected String getDaoFaceName(DaoLayerGenerateModel bean){
		return "I" + getDaoName(bean);
	}

	@Override
	protected List<String> generateFields(DaoLayerGenerateModel bean) {
		List<String> result = new ArrayList<String>();
		StringBuilder sb = new StringBuilder();
		sb.append("@Autowired  \n");
		sb.append("@Qualifier(\""+bean.getJdbcTemplateName()+"\") \n");
		sb.append("private JdbcTemplate jdbcTemplate ;");
		result.add(sb.toString());
		return result;
	}

	@Override
	protected List<String> generateMethods(DaoLayerGenerateModel bean) {
		List<String> result = new ArrayList<String>();
		for(AbstractMethodGenerateModel method : bean.getMethodModelList()){
			if(method instanceof  MethodDeleteModel){
				result.addAll(generateDeleteMethod((MethodDeleteModel)method));
			} else if(method instanceof  MethodUpdateModel){
				result.addAll(generateUpdateMethod((MethodUpdateModel)method));
			} else if(method instanceof  MethodSelectModel){
				result.addAll(generateSelectMethod((MethodSelectModel)method));
			} else if(method instanceof  MethodInsertModel){
				result.addAll(generateInsertMethod((MethodInsertModel)method));
			}
		}
		return result;
	}
	
	
	private List<String> generateInsertMethod(MethodInsertModel methodModel) {
		StringBuilder methodBuilder = new StringBuilder();
		methodBuilder.append(generateMethodDeclare(methodModel)).append(" {");
		StringBuilder params = new StringBuilder();
		params.append(generateSelectParams(methodModel));
		methodBuilder.append(FreemarkerUtil.formatDaoTemplate(insertSqlGenerator.generate(methodModel), params.toString()));
		methodBuilder.append("}");
		return Arrays.asList(methodBuilder.toString());
	}
	
	private List<String> generateDeleteMethod(MethodDeleteModel methodModel) {
		StringBuilder methodBuilder = new StringBuilder();
		methodBuilder.append(generateMethodDeclare(methodModel)).append(" {");
		StringBuilder params = new StringBuilder();
		params.append(generateSelectParams(methodModel));
		methodBuilder.append(FreemarkerUtil.formatDaoTemplate(deleteSqlGenerator.generate(methodModel), params.toString()));
		methodBuilder.append("}");
		return Arrays.asList(methodBuilder.toString());
	}

	
	private List<String> generateUpdateMethod(MethodUpdateModel methodModel) {
		StringBuilder methodBuilder = new StringBuilder();
		methodBuilder.append(generateMethodDeclare(methodModel)).append(" {");
		StringBuilder params = new StringBuilder();
		params.append(generateSelectParams(methodModel));
		methodBuilder.append(FreemarkerUtil.formatDaoTemplate(updateSqlGenerator.generate(methodModel), params.toString()));
		methodBuilder.append("}");
		return Arrays.asList(methodBuilder.toString());
	}
	
	private List<String> generateSelectMethod(MethodSelectModel methodModel) {
		List<String> result = new ArrayList<String>();
		StringBuilder functionMethodBuilder = new StringBuilder();
		functionMethodBuilder.append(generateSelectMethodDeclare(methodModel) + " {");
		result.add(functionMethodBuilder.toString());
		result.addAll(generateSelectMethodContent(methodModel));
		result.add("}");
		return result;
	}
	
	
	private List<String> generateSelectMethodContent(MethodSelectModel methodModel) {
		List<FmtFieldModel> resultList = new ArrayList<FmtFieldModel>();
		for(FieldGenerateModel item : methodModel.getQueryResultList()){
			FmtFieldModel fmtField = new FmtFieldModel(item.getPropertyNameByFirstLetterUpper(),item.getValueType().getNameByFirstLetterUpper(),item.getColumnName());
			resultList.add(fmtField);
		}
		String content = null;
		if(methodModel.getMethodResultType() == MethodResultType.select_bean){
			content = FreemarkerUtil.formatDaoSelectOneBeanTemplate(methodModel.getBeanGenerateModel().getBeanNameByFirstLetterUpper(), generateSelectSql(methodModel), resultList,generateSelectParams(methodModel));
		}else {
			content = FreemarkerUtil.formatDaoSelectListBeanTemplate(methodModel.getBeanGenerateModel().getBeanNameByFirstLetterUpper(), generateSelectSql(methodModel), resultList,generateSelectParams(methodModel));
		}
		return Arrays.asList(content);
	}
	
	
	private String generateSelectSql(MethodSelectModel methodModel){
		return querySqlGenerator.generate(methodModel);
	}
	
	
	@Override
	protected String generatePackage(DaoLayerGenerateModel bean) {
		return "package " + bean.getPackageName() + Contants.$lineSplit;
	}

}
